package com.ys.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.TcwCapitalClaim;
import com.ys.entity.finance.TcwCapitalClaimSon;
import com.ys.entity.finance.TcwCapitalRegisterClaim;
import com.ys.entity.finance.TcwFinancialTransactionFlow;
import com.ys.entity.flow.YspModel;
import com.ys.entity.hr.ThrOperateCompanyApply;
import com.ys.entity.hr.ThrOperateCompanyBankInfo;
import com.ys.entity.sys.*;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.finance.TcwFinancialTransactionFlowEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.finance.*;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.finance.TcwCapitalClaimService;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.DateUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 资金认领单
 */
@Service("tcwCapitalClaim")
public class TcwCapitalClaimServiceImpl implements TcwCapitalClaimService {
	private static final Logger logger = LoggerFactory.getLogger(TcwCapitalClaimServiceImpl.class);

	@Autowired
	private TcwCapitalClaimMapper tcwCapitalClaimMapper;

	@Autowired
	private TcwCapitalClaimSonMapper tcwCapitalClaimSonMapper;

	@Autowired
	private TcwCapitalRegisterClaimMapper tcwCapitalRegisterClaimMapper;

	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private FinanceMapper financeMapper;

	@Autowired
	private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;

	@Autowired
	private TcwFinancialTransactionFlowMapper tcwFinancialTransactionFlowMapper;

	private final Long GRID = 25L;

	/**
	 * 新增
	 */
	@Override
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwCapitalClaim tcwCapitalClaim = JSON.parseObject(JSON.toJSONString(params), TcwCapitalClaim.class);
		tcwCapitalClaim.setStatus(1);//状态
		tcwCapitalClaim.setEffectStock(0);//审批状态

		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setOrderby("A.CreateTime DESC").queryFirst();
		if(tsUserChange!=null){
			tcwCapitalClaim.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,tcwCapitalClaim);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		//新增
		tcwCapitalClaimMapper.insert(tcwCapitalClaim);

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, tcwCapitalClaim.getBid(), createUserId);
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/finance/tcwCapitalClaim/toEdit?bid=" + tcwCapitalClaim.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwCapitalClaim tcwCapitalClaim = JSON.parseObject(JSON.toJSONString(params), TcwCapitalClaim.class);
		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(tcwCapitalClaim.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("已流转，无法编辑");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,tcwCapitalClaim);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}
		tcwCapitalClaimMapper.update(tcwCapitalClaim);
		return R.ok();
	}


	//保存列表信息
	public R saveItem(Map<String, Object> params,TcwCapitalClaim tcwCapitalClaim) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID,params);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		for (int i = 0; i < subDataList.size(); i++) {
			Map<String, Object> item = subDataList.get(i);
			TcwCapitalClaimSon tcwCapitalClaimSon = JSON.parseObject(JSON.toJSONString(item), TcwCapitalClaimSon.class);
			tcwCapitalClaimSon.setStatus(1);
			tcwCapitalClaimSon.setPbid(tcwCapitalClaim.getBid());
			if(tcwCapitalClaimSon.getId()!=null){
				//修改
				tcwCapitalClaimSonMapper.update(tcwCapitalClaimSon);
			}else {
				//新增
				tcwCapitalClaimSonMapper.insert(tcwCapitalClaimSon);
			}
		}
		return R.ok();
	}


	//删除
	@Override
	@Transactional
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TcwCapitalClaim entity = new TcwCapitalClaim().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tcwCapitalClaimMapper.deleteTrue(id);
		//删除列表信息
		financeMapper.deleteTcwCapitalClaimSonByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}

	//删除列表
	@Override
	@Transactional
	public R toDelByItem(Long id) throws Exception{
		tcwCapitalClaimSonMapper.deleteTrue(id);
		return R.ok();
	}



	/**
	 * 流转通过
	 */
	@Override
	@Transactional
	public R flowPass(Long id, String loginUserId) throws Exception {

		TcwCapitalClaim entity = new TcwCapitalClaim().setId(id).queryFirst();
		Flow f = yspTaskService.flowPass(entity.getBid(), loginUserId);
		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			if (f.getState() == Flow.State.FINISH.value) {
				flowFinish(entity.getBid());
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	@Override
	@Transactional
	public void flowFinish(String bid) throws Exception {

		TcwCapitalClaim entity = new TcwCapitalClaim().setBid(bid).queryFirst();
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return;
		}
		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		//获取详情信息
		List<TcwCapitalClaimSon> tcwCapitalClaimSonList = new TcwCapitalClaimSon().setPbid(bid).queryList();
		for (TcwCapitalClaimSon sonItem : tcwCapitalClaimSonList){
			//修改资金登记认领表状态信息
			TcwCapitalRegisterClaim tcwCapitalRegisterClaim = new TcwCapitalRegisterClaim().setId(sonItem.getCapitalRegisterClaimId()).queryFirst();
			if(tcwCapitalRegisterClaim!=null){
				//tcwCapitalRegisterClaim.setId(sonItem.getCapitalRegisterClaimId());//id
				tcwCapitalRegisterClaim.setClaimStatus(1);//认领状态（0未认领、1已认领)
				tcwCapitalRegisterClaim.setClaimTime(theDate);//认领时间
				tcwCapitalRegisterClaim.setClaimVgsbm(entity.getClaimVgsbm());//认领公司编码
				tcwCapitalRegisterClaimMapper.update(tcwCapitalRegisterClaim);
				ThrOperateCompanyBankInfo thrOperateCompanyBankInfo = new ThrOperateCompanyBankInfo().setId(sonItem.getOperateCompanyBankInfoId()).queryFirst();
				ThrOperateCompanyApply thrOperateCompanyApply = new ThrOperateCompanyApply().setVgsbm(entity.getClaimVgsbm()).queryFirst();
				if(thrOperateCompanyBankInfo!=null && thrOperateCompanyApply!=null){
					/**
					 * 新增一条流水
					 * 必填：vgsbm划出公司编码；vgsbmp划入公司编码；vjylx交易类型；fje交易金额；djysj交易时间；dshsj审核时间；vbz备注
					 * 选填：mname;mtype;mnid;mbid;mguid；writeTime记账时间（如果为空，默认审核时间）
					 */
					Date writeTime = DateUtil.parseYYYY_MM_dd_HH_mm_ss(sonItem.getPaymentTime()+" 00:00:00");
					tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJc(
							entity.getClaimVgsbm(),thrOperateCompanyApply.getVgsjc(),"GS0874","挂账账户",
							sonItem.getVjylx(), sonItem.getPaymentAmount(),entity.getCreateTime(), theDate,"资金认领单："+entity.getBid(),entity.getBid(),
							writeTime);

					tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJc(
							"GS0874","挂账账户",entity.getClaimVgsbm(),thrOperateCompanyApply.getVgsjc(),
							sonItem.getVjylx(), BigDecimal.ZERO.subtract(sonItem.getPaymentAmount()),entity.getCreateTime(), theDate,"资金认领单："+entity.getBid(),
							entity.getBid(),writeTime);


					//查询资金登记单子表产生的财务流水
					TcwFinancialTransactionFlow flowInfo = new TcwFinancialTransactionFlow()
							.setFromId(tcwCapitalRegisterClaim.getCapitalRegisterSonId())
							.setFromType(TcwFinancialTransactionFlowEnum.FromType.TCW_CapitalRegisterSon.value)
							.queryFirst();

					if(flowInfo!=null && flowInfo.getId()!=null){
						//获取财务交易类型
						String transactionTypeStr = TransactionTypeEnum.FinanceType.TCW_CapitalRegister.name;
						TbBaseInfo transactionTypeItem = tcwFinancialTransactionFlowService.getTransactionType(transactionTypeStr);
						if(transactionTypeItem!=null && transactionTypeItem.getId()!=null){
							flowInfo.setTransactionTypeBid(transactionTypeItem.getBid());
							tcwFinancialTransactionFlowMapper.update(flowInfo);
						}
					}
				}
			}

		}

		//修改信息
		tcwCapitalClaimMapper.update(entity);

	}



	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCW_CapitalClaim",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		return backMsg;
	}



	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId, Map<String, Object> params) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow += checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCW_CapitalClaimSon",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("paymentTime")//收款时间
										|| ysColItem.getCode().equals("operateCompanyBankInfoId")//运营公司银行账户
										|| ysColItem.getCode().equals("capitalRegisterClaimId")//资金登记认领表
										|| ysColItem.getCode().equals("paymentAmount")//付款金额
										|| ysColItem.getCode().equals("vjylx")//交易类型

				);


				//当为对公账户时，登记登记银行户名需要=认领运营公司名称
				if(checkUtil.isNotNullByObject(subData.get("accountType")) && subData.get("accountType").toString().equals("0")){
					if(checkUtil.isNotNullByObject(subData.get("paymentVyhzhmc"))){
						if(!subData.get("paymentVyhzhmc").toString().equals(params.get("vgsmc").toString())){
							backMsgByRow += "当为对公账户时，登记登记银行户名需要等于认领运营公司名称！";
						}
					}else {
						backMsgByRow += "当为对公账户时，登记登记银行户名需要等于认领运营公司名称！";
					}
				}


				//金额验证
				if(checkUtil.isNotNullByObject(subData.get("paymentAmount")) && checkUtil.isNotNullByObject(subData.get("paymentAmountByClaim"))){
					if(!subData.get("paymentAmount").toString().equals(subData.get("paymentAmountByClaim").toString())){
						backMsgByRow += "付款金额应与登记金额一致；";
					}
				}

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}


	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{
		Map<String,Object> extraParam = new TcwCapitalClaim()
				.addLeftJoin("THR_OperateCompanyApply OCA ON OCA.Vgsbm = A.ClaimVgsbm ")
				.addField("OCA.Vgsjc AS vgsjc")//认领运营公司简称
				.addField("OCA.Vgsmc AS vgsmc")//认领运营公司名称

				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid AND 1=1")
				.addField("P.Bid AS instBid")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间
				.addLeftJoin("(SELECT ISNULL(SUM(S.PaymentAmount),0) AS paymentAmount,S.Pbid FROM TCW_CapitalClaimSon S GROUP BY S.Pbid) B ON B.Pbid = A.Bid")
				.addField("B.paymentAmount AS totalAmount")//付款总金额

				.setBid(bid)
				.queryFirstMap();
		return extraParam;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> itemList = new TcwCapitalClaimSon()

				.addLeftJoin("THR_OperateCompanyBankInfo B ON B.Id = A.OperateCompanyBankInfoId")//运营公司银行账户管理
				.addField("B.Vid AS vid")//账户编码
				.addField("B.Vyhzhmc AS vyhzhmc")//付款银行户名
				.addField("B.Vkhh AS vkhh")//付款开户行
				.addField("B.Vyhzh AS vyhzh")//付款银行账号
				//.addField("'运营服务→预付款' AS vjylx")//交易类型

				.addLeftJoin("TCW_CapitalRegisterClaim C ON C.Id = A.CapitalRegisterClaimId")//资金登记认领表
				.addLeftJoin("TCW_CapitalRegisterSon CS ON CS.Id = C.CapitalRegisterSonId")//资金登记单详情
				.addLeftJoin("THR_OperateCompanyBankInfo BI ON BI.Id = C.OperateCompanyBankInfoId")//运营公司银行账户管理
				.addLeftJoin("THR_OperateCompanyApply OC ON OC.Vgsbm = C.AccountingVgsbm")//运营公司银行账户管理

				.addField("CS.Pbid AS capitalRegisterBid")//资金登记单单号
				.addField("BI.Vyhzhmc AS paymentVyhzhmc")//登记银行户名
				.addField("BI.Vkhh AS paymentVkhh")//登记开户行
				.addField("BI.Vyhzh AS paymentVyhzh")//登记银行账号
				.addField("BI.AccountType AS accountType")//账户类型
				.addField("CASE " +
						"WHEN BI.AccountType = 0 THEN '对公户' " +
						"WHEN BI.AccountType  = 1 THEN '个人户' " +
						" ELSE '' END accountTypeTxt")//账户类型

				.addField("C.PaymentTime AS paymentTimeByClaim")//登记时间
				.addField("C.PaymentAmount AS paymentAmountByClaim")//登记金额

				.addField("'GS0874' AS accountingVgsbm")//登记公司编码
				.addField("'挂账账户' AS accountingVgsmc")//登记公司名称

				.setPbid(bid)
				.queryMap();
		return itemList;
	}


	@Override
	@Transactional
	public TcwCapitalClaim setSeachSql(TcwCapitalClaim cond)throws Exception{

		cond.addLeftJoin("TS_UserChange U ON U.Id = A.CreateChangeId ")
				.addField("U.UserId + '/' + U.UserName AS _ys_createUserName")//制单人
				.addField("U.DeptName AS deptName")//制单人部门
				.addField("FORMAT(A.CreateTime, 'yyyy-MM-dd HH:mm:ss') AS createTimeByStr")//创建时间


				.addLeftJoin("TS_UserInfo CU ON CU.UserId = U.UserId")//用户信息表
				.addLeftJoin("TS_OrganizationInfo UO ON UO.Id = CU.OrgId")//用户所属机构

				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				//.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间
				.addField("CASE WHEN P.UpdateTime IS NULL AND A.EffectStock = 1 THEN FORMAT(A.UpdateTime, 'yyyy-MM-dd HH:mm:ss') ELSE FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') END auditingTime")//审核时间

				.addLeftJoin("THR_OperateCompanyApply OCA ON OCA.Vgsbm = A.ClaimVgsbm ")
				.addField(" OCA.Vgsmc claimVgsmc ")
				.addField("OCA.Vgsjc AS vgsjc")//认领运营公司简称
				.addField("OCA.Cuser AS cuser")//运营人



				.addLeftJoin("TCW_CapitalClaimSon S ON S.Pbid = A.Bid")//子表
				.addField("S.PaymentTime AS paymentTime")//付款时间
				.addField("S.PaymentAmount AS paymentAmount")//付款金額

				.addLeftJoin("THR_OperateCompanyBankInfo B ON B.Id = S.OperateCompanyBankInfoId")//运营公司银行账户管理
				.addField("B.Vid AS vid")//账户编码
				.addField("B.Vyhzhmc AS vyhzhmc")//付款银行户名
				.addField("B.Vkhh AS vkhh")//付款开户行
				.addField("B.Vyhzh AS vyhzh")//付款银行账号
				.addField("'运营服务→预付款' AS vjylx")//交易类型

				.addLeftJoin("TCW_CapitalRegisterClaim C ON C.Id = S.CapitalRegisterClaimId")//资金登记认领表
				.addLeftJoin("THR_OperateCompanyBankInfo BI ON BI.Id = C.OperateCompanyBankInfoId")//运营公司银行账户管理
				.addField("BI.Vyhzhmc AS paymentVyhzhmc")//登记银行户名
				.addField("BI.Vkhh AS paymentVkhh")//登记开户行
				.addField("BI.Vyhzh AS paymentVyhzh")//登记银行账号
				.addField("BI.AccountType AS accountType")//账户类型
				.addField("CASE " +
						"WHEN BI.AccountType = 0 THEN '对公户' " +
						"WHEN BI.AccountType  = 1 THEN '个人户' " +
						" ELSE '' END accountTypeTxt")//账户类型
				.addLeftJoin("TS_UserChange QWE ON QWE.Id = A.CreateChangeId")



				.addLeftJoin("TCW_CapitalRegisterSon CRS ON CRS.Id = C.CapitalRegisterSonId")//
				.addField("CRS.Pbid AS capitalRegisterBid")//

				.addLeftJoin("TCW_CapitalRegister CRSP ON CRSP.Bid = CRS.Pbid")//
				.addLeftJoin("TB_CompanyInfo CRSPC ON CRSPC.Vid = CRSP.CompanyVid ")
				.addField("CRSPC.Vname AS companyVname")//收款公司名称

				//排序
				.setOrderby("A.Bid DESC");

		return  cond;
	}


}
